package com.share.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.share.admin.mapper.MenuMapper;
import com.share.admin.model.db.Menu;
import com.share.admin.model.vo.MenuPageReq;
import com.share.admin.model.vo.MenuVo;
import com.share.admin.service.IMenuService;
import com.share.common.common.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表  服务实现类
 * </p>
 *
 * @author author
 * @since 2022-09-22
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {
    private final static String LEFT_MENU_NODE_TYPE[] = new String[]{"M", "D", "L"}; //左边的菜单
    @Resource
    private MenuMapper menuMapper;

    @Override
    public Set<String> permissionByMenuId(Long menuId) {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pid", menuId);/*找子节点*/
        queryWrapper.orderByAsc("pid").orderByAsc("sort");//排序 父节点,序号
        List<Menu> list = menuMapper.selectList(queryWrapper);
        Set<String> set = list.stream().map(e -> e.getPermission()).filter(e -> StringUtils.isNotBlank(e)).collect(Collectors.toSet());
        return set;
    }

    @Override
    public Set<String> permissionByMenuIdAndUserId(Long menuId, Long userId) {
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("menuId", menuId);/*找子节点*/
        Set<Menu> list = menuMapper.listMenuByMenuPidAndUserId(map);
        Set<String> set = list.stream().map(e -> e.getPermission()).filter(e -> StringUtils.isNotBlank(e)).collect(Collectors.toSet());
        return set;
    }


    @Override
    public Set<String> permissionByUserId(Long userId) {
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        Set<Menu> list = menuMapper.selectMenuByUserIdAndNodeType(map);

        Set<String> set = list.stream().map(e -> e.getPermission()).filter(e -> StringUtils.isNotBlank(e)).collect(Collectors.toSet());
        return set;
    }

    @Override
    public Set<String> permissionAll() {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("pid").orderByAsc("sort");//排序 父节点,序号
        List<Menu> list = menuMapper.selectList(queryWrapper);
        Set<String> set = list.stream().map(e -> e.getPermission()).filter(e -> StringUtils.isNotBlank(e)).collect(Collectors.toSet());
        return set;
    }

    @Override
    public Set<Menu> listByRoleId(Long roleId) {
        return menuMapper.listByRoleId(roleId);
    }

    @Override
    public Set<Menu> listByUserId(Long userId) {
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("nodeType", LEFT_MENU_NODE_TYPE);
        Set<Menu> menus = menuMapper.selectMenuByUserIdAndNodeType(map);

        //需要排序
        Set<Menu> set = new HashSet<>();
        set.addAll(menus);
        return set;
    }

    @Override
    public Set<Menu> listAll() {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1);
        queryWrapper.in("node_type", LEFT_MENU_NODE_TYPE);/*只筛选目录和菜单和链接*/
        queryWrapper.orderByAsc("pid").orderByAsc("sort");//排序 父节点,序号
        List<Menu> list = menuMapper.selectList(queryWrapper);

        //需要排序
        Set<Menu> set = new HashSet<>();
        set.addAll(list);
        return set;
    }

    @Override
    public Set<MenuVo> treeAll() {
        Set<Menu> list = listAll();
        return tree(list);
    }

    @Override
    public Set<MenuVo> treeByUserId(Long userId) {
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("nodeType", LEFT_MENU_NODE_TYPE);
        Set<Menu> list = menuMapper.selectMenuByUserIdAndNodeType(map);
        return tree(list);
    }

    // 把Menu转换为树形结构
    private Set<MenuVo> tree(Set<Menu> list) {
        //组装为map
        Set<Long> pidInNullList = new HashSet<>();
        Map<Long, MenuVo> menuMap = new HashMap<Long, MenuVo>();
        for (Menu menu : list) {// 根据权限创建菜单
            MenuVo menuVo = new MenuVo();
            BeanUtils.copyProperties(menu, menuVo);
            menuMap.put(menu.getId(), menuVo);
            if (menu.getPid() == null) {
                pidInNullList.add(menu.getId());
            }
        }

        /*组装树*/
        for (Menu m1 : list) {
            MenuVo menu1 = menuMap.get(m1.getId());
            for (Menu m2 : list) {
                if (m1.getId() != null && m2.getPid() != null && m1.getId().toString().equals(m2.getPid().toString())) {
                    MenuVo menu2 = menuMap.get(m2.getId());
                    List<MenuVo> tmpChildrenList = menu1.getChildren();
                    if (tmpChildrenList == null) {
                        tmpChildrenList = new LinkedList<>();
                        menu1.setChildren(tmpChildrenList);
                    }
                    tmpChildrenList.add(menu2);
                    //执行一次排序
                    Collections.sort(tmpChildrenList);
                }
            }
        }

        /*提取出所有的树*/
        Set<MenuVo> reList = new LinkedHashSet<>();
        for (Long id : pidInNullList) {
            MenuVo menuVo = menuMap.get(id);
            reList.add(menuVo);
        }

        //TreeSet用起来很奇怪,这里手动排序,LinkedHashSet 才可以排序
        reList = reList.stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new));
        return reList;
    }

    @Override
    public Page pageList(MenuPageReq req) {
        PageHelper.startPage(req.getPageNum(), req.getPageSize());
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(req.getComponent())) {
            queryWrapper.like(Menu::getComponent, req.getComponent());
        }
        if (StringUtils.isNotBlank(req.getName())) {
            queryWrapper.like(Menu::getName, req.getName());
        }
        if (StringUtils.isNotBlank(req.getPath())) {
            queryWrapper.like(Menu::getPath, req.getPath());
        }
        if (StringUtils.isNotBlank(req.getStatus())) {
            queryWrapper.like(Menu::getStatus, req.getStatus());
        }
        if (StringUtils.isNotBlank(req.getNodeType())) {
            queryWrapper.like(Menu::getNodeType, req.getNodeType());
        }
        if (StringUtils.isNotBlank(req.getPermission())) {
            queryWrapper.like(Menu::getPermission, req.getPermission());
        }
        if (StringUtils.isNotBlank(req.getIcon())) {
            queryWrapper.like(Menu::getIcon, req.getIcon());
        }
        List<Menu> list = menuMapper.selectList(queryWrapper);
        return new Page<>(list, new PageInfo<>(list).getTotal(), req);
    }

}
